/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "PBF.h"

#include "core/引擎配置.h"
#include "物体/物体.h"
#include "面/面.h"
#include "粒子/粒子.h"
#include "文件/加载保存属性.h"
#include "底层绘图/intern/绘图框架.h"

#include <随机数.h>
#include <file_文件名数据.h>



static double W(vec3 r, double h) {
	double len = length(r);
	double q = len / h;

	if (q <= 1)
		return 315 / (64 * M_PI * pow(h, 9)) * pow((pow(h, 2) - pow(q, 2)), 3);
	else if (q <= 2)
		return 315 / (64 * M_PI * pow(h, 9)) * pow((2 - q), 3) * pow(q, 2);
	else
		return 0;
}

static vec3 gradW(vec3 r, double h) {
	double len = length(r);
	double q = len / h;
	vec3 grad;

	if (q <= 1)
		grad = vec3{ float32(-945 / (32 * M_PI * pow(h, 9)) * r.x * pow(h * h - q * q, 2)),
					  float32(-945 / (32 * M_PI * pow(h, 9)) * r.y * pow(h * h - q * q, 2)),
					  float32(-945 / (32 * M_PI * pow(h, 9)) * r.z * pow(h * h - q * q, 2)) };
	else if (q <= 2)
		grad = vec3{ float32(-945 / (64 * M_PI * pow(h, 9)) * r.x * q * (2 - q) * (2 - q)) ,
					  float32(-945 / (64 * M_PI * pow(h, 9)) * r.y * q * (2 - q) * (2 - q)) ,
					  float32(-945 / (64 * M_PI * pow(h, 9)) * r.z * q * (2 - q) * (2 - q)) };
	else
		grad = vec3{ 0, 0, 0 };

	return grad;
}

static double lapW(vec3 r, double h) {
	double len = length(r);
	double q = len / h;

	if (q <= 1)
		return 945 / (32 * M_PI * pow(h, 9)) * (h * h - q * q) * (7 * q * q - 3 * h * h);
	else if (q <= 2)
		return 945 / (64 * M_PI * pow(h, 9)) * h * q * (3 * q - 2);
	else
		return 0;
}

static float kernel(float r, float h) {
	float q = r / h;
	float result;

	if (q <= 1.0f) {
		result = (1 - 1.5f * q * q + 0.75f * q * q * q) / (M_PI * pow(h, 3));
	}
	else if (q <= 2.0f) {
		result = 0.25f * pow((2 - q), 3) / (M_PI * pow(h, 3));
	}
	else {
		result = 0.0f;
	}

	return result;
}


Inline S_ParticleAttr f_物体类型和状态(E_物理体类型 类型, uint32 是否启用, float32 寿命 = 1e+8) {
	return {(类型<<16) | 是否启用, 0, 0, 寿命 };
}

//Inline S_ParticleAttr f_物体粒子寿命(E_物理体类型 类型, uint32 是否启用, float32 寿命 = 1e+8) {
//	return { (类型 << 16) | 是否启用, 0, 0, 寿命 };
//}



S_PhysicspPBF::S_PhysicspPBF(S_设备环境& ctx, std::wstring name) {
	m_设备 = ctx;
	m_计数层 = f_ob_创建渲染层(ctx);


	std::vector<S_着色器创建参数> 参数配置 = {
	};
	std::vector<S_常量推送创建参数> 施加力_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_ParticleGrid_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 粒子排序_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_RadixSort_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 粒子区间偏移_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_MapRange_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 粒子排序合并_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_CombiningSort_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 粒子力_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_ParticleForce_ConstPush)},
	};
	std::vector<S_着色器创建参数> 参数配置_碰撞 = {
		{DEF_BINDING_topLAS, E_着色阶段::e_计算着色, E_板载缓存类型::e_光追BVH},
		{DEF_BINDING_Ray_ObMesh, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
	};


	std::vector<S_常量推送创建参数> 飞溅粒子排序_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_DiffuseCombining_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 飞溅粒子力_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_GenDiffuse_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 飞溅粒子发射_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_DiffuseEmission_ConstPush)},
	};

	 
	m_GPU计算_粒子施加力 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "粒子施加力.spv", 参数配置, 施加力_常量);

	m_GPU计算_粒子排序 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "映射索引排序.spv", 参数配置, 粒子排序_常量);
	m_GPU计算_粒子排序偏移 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "排序映射索引偏移.spv", 参数配置, 粒子区间偏移_常量);
	m_GPU计算_粒子排序偏移复制 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "排序映射索引偏移拷贝.spv", 参数配置, 粒子区间偏移_常量);
	m_GPU计算_粒子排序合并 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "排序映射索引合并.spv", 参数配置, 粒子排序合并_常量);
	m_GPU计算_粒子排序合并复制 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "排序映射索引合并复制.spv", 参数配置, 粒子排序合并_常量);

	m_GPU计算_清除粒子在网格索引 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "清除粒子在网格索引.spv", 参数配置, 施加力_常量);
	m_GPU计算_粒子在网格索引 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "粒子在网格索引.spv", 参数配置, 施加力_常量);
	
	m_GPU计算_计算密度和压力 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算密度和压力.spv", 参数配置, 粒子力_常量);
	m_GPU计算_粒子力计算 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算作用力.spv", 参数配置, 粒子力_常量);
	m_GPU计算_粒子碰撞更新 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "粒子碰撞更新.cspv", 参数配置_碰撞, 粒子力_常量);
	m_GPU计算_粒子粘力 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算粒子粘度.cspv", 参数配置, 粒子力_常量);


	m_GPU计算_飞溅粒子生成排序键值 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子生成排序键值.spv", 参数配置, 飞溅粒子排序_常量);
	m_GPU计算_飞溅粒子排序偏移 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子排序偏移.spv", 参数配置, 飞溅粒子排序_常量);
	m_GPU计算_飞溅粒子排序偏移复制 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子排序偏移复制.spv", 参数配置, 飞溅粒子排序_常量);
	m_GPU计算_飞溅粒子排序合并 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子排序合并.spv", 参数配置, 飞溅粒子排序_常量);
	m_GPU计算_计算飞溅粒子生成 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算飞溅粒子生成.spv", 参数配置, 飞溅粒子力_常量);
	m_GPU计算_计算飞溅粒子运动 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算飞溅粒子运动.spv", 参数配置, 飞溅粒子力_常量);

	m_GPU计算_飞溅粒子发射排序 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子发射排序.spv", 参数配置, 飞溅粒子发射_常量);
	m_GPU计算_飞溅粒子发射排序偏移 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子发射排序偏移.spv", 参数配置, 飞溅粒子发射_常量);
	m_GPU计算_飞溅粒子发射排序偏移复制 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子发射排序偏移复制.spv", 参数配置, 飞溅粒子发射_常量);
	m_GPU计算_飞溅粒子发射排序合并 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "飞溅粒子发射排序合并.spv", 参数配置, 飞溅粒子发射_常量);

	//m_GPU计算_计算飞溅粒子更新 = f_gpu_创建并行计算实例(ctx, S_引擎配置::m_3D着色器文件根路径 + "计算飞溅粒子更新.spv", 参数配置, 飞溅粒子排序_常量);




	std::vector<S_常量推送创建参数> 粒子可视_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_ParticleDEBUG_ConstPush)},
	};
	std::vector<S_常量推送创建参数> 粒子域可视_常量 = {
		{E_着色阶段::e_计算着色, 0, sizeof(S_PBF_DomainDEBUG_ConstPush)},
	};
	m_GPU计算_粒子可视 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "调试_粒子可视.spv", 参数配置, 粒子可视_常量);
	m_GPU计算_域可视 = f_df_创建并行计算(ctx, S_引擎配置::m_3D着色器文件根路径 + "调试_域可视.spv", 参数配置, 粒子域可视_常量);


	m_碰撞参数 = {};
	f_df_allocGPU参数缓存槽(&m_碰撞参数, 2);



	m_坐标 = {};
	m_质量 = {};
	//m_速度 = {};
	m_加速度 = {};
	m_碰撞质量_密度_lambda = {};
	m_粒子类型状态 = {};


	m_排序键值 = {};
	m_排序临时键值 = {};
	m_排序键值偏移A = {};
	m_排序键值偏移B = {};
	m_排序键值区间数量 = {};
	m_排序跳过交换 = {};

	m_飞溅坐标 = {};
	m_飞溅速度 = {};
	m_飞溅寿命 = {};
	m_飞溅粒子排序键值 = {};
	m_飞溅粒子发射排序键值A = {};
	m_飞溅粒子发射排序键值B = {};
	m_飞溅粒子排序区间数量 = {};
	m_发射飞溅粒子排序键值偏移A = {};
	m_发射飞溅粒子排序键值偏移B = {};

	m_力 = {};

	m_MumIterations = 1;
	m_NumSubsteps = 1;


	m_已有飞溅粒子数量 = 0;
	m_已有发射粒子索引数量A = 0;
	m_已有发射粒子索引数量B = 0;
	m_有效飞溅粒子数量 = 0;


	m_开启飞溅粒子 = false;
}

S_PhysicspPBF::~S_PhysicspPBF() {
	f_df_销毁并行计算(m_GPU计算_粒子施加力);

	f_df_销毁并行计算(m_GPU计算_粒子排序);
	f_df_销毁并行计算(m_GPU计算_粒子排序偏移);
	f_df_销毁并行计算(m_GPU计算_粒子排序偏移复制);
	f_df_销毁并行计算(m_GPU计算_粒子排序合并);

	f_df_销毁并行计算(m_GPU计算_清除粒子在网格索引);
	f_df_销毁并行计算(m_GPU计算_粒子在网格索引);
	
	f_df_销毁并行计算(m_GPU计算_粒子力计算);

	f_df_销毁并行计算(m_GPU计算_飞溅粒子发射排序);
	f_df_销毁并行计算(m_GPU计算_飞溅粒子发射排序偏移);
	f_df_销毁并行计算(m_GPU计算_飞溅粒子发射排序偏移复制);


	f_df_销毁并行计算(m_GPU计算_粒子可视);
	f_df_销毁并行计算(m_GPU计算_域可视);


	f_bm_erase(m_坐标);
	f_bm_erase(m_质量);
	//f_buf_erase(m_速度);
	f_bm_erase(m_加速度);
	f_bm_erase(m_碰撞质量_密度_lambda);
	f_bm_erase(m_Delta);
	f_bm_erase(m_粒子类型状态);

	f_bm_erase(m_排序键值);
	f_bm_erase(m_排序临时键值);
	f_bm_erase(m_排序键值偏移A);
	f_bm_erase(m_排序键值偏移B);
	f_bm_erase(m_排序键值区间数量);
	f_bm_erase(m_排序跳过交换);


	f_bm_erase(m_单元粒子索引网格);
	//f_buf_erase(m_单元粒子数量网格);


	f_bm_erase(m_飞溅坐标);
	f_bm_erase(m_飞溅速度);
	f_bm_erase(m_飞溅粒子排序键值);
	f_bm_erase(m_飞溅粒子排序区间数量);
	f_bm_erase(m_发射飞溅粒子排序键值偏移A);
	f_bm_erase(m_发射飞溅粒子排序键值偏移B);
}

void S_PhysicspPBF::f_Update() {
	
}

void S_PhysicspPBF::f_划分粒子() {
	uint32 num = m_坐标.m_Mem.m_数量 / DEF_PBF_GroupSize;

	S_PBF_ParticleGrid_ConstPush 参数;
	参数.m_Address_Particle = f_buf_getOffsetAddress(m_坐标);
	参数.m_Address_OldParticle = f_buf_getOffsetAddress(m_前一帧坐标);
	参数.m_Address_Velocity = f_buf_getOffsetAddress(m_速度和年龄);
	参数.m_Address_Acceleration = f_buf_getOffsetAddress(m_加速度);
	参数.m_Address_Mass = f_buf_getOffsetAddress(m_碰撞质量_密度_lambda);
	参数.m_Address_Force = f_buf_getOffsetAddress(m_力);
	参数.m_Address_TypeState = f_buf_getOffsetAddress(m_粒子类型状态);
	参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
	参数.m_Address_SimParam = f_buf_getOffsetAddress(m_解算参数);
	

	参数.m_gridOffset = m_域偏移;
	参数.m_dim = _iVec3(m_网格分辨率);
	参数.m_cellSize = m_网格单元大小;
	参数.m_particleCount = m_粒子数量;
	参数.m_forceCount = m_力.m_Mem.m_数量;

	参数.m_min_bound = m_域偏移;
	参数.m_max_bound = m_域偏移 + _Vec3(m_网格分辨率) * m_网格单元大小;

	f_GPU_run计算(m_GPU计算_粒子施加力, { num, 1, 1 }, &参数, sizeof(S_PBF_ParticleGrid_ConstPush));


	//auto* key = f_buf_uVec2_ptr(m_排序键值);
	//for (uint32 k = 0; k < m_排序键值.m_Mem.m_数量; ++k) {
	//	std::cout << k << " b " << key[k].x << " " << key[k].y << " " << bool(key[k].y & 1) << std::endl;
	//}
	//S_PBF_DiffuseCombining_ConstPush 飞溅粒子生成参数{};
	//飞溅粒子生成参数.m_Address_Acceleration = f_buf_getAddress(m_速度);
	//飞溅粒子生成参数.m_Address_Mass = f_buf_getAddress(m_质量密度);
	//飞溅粒子生成参数.m_Address_IndexKey_a = f_buf_getAddress(m_排序临时键值);
	//飞溅粒子生成参数.m_Address_KeyOffset_a = f_buf_getAddress(m_排序键值偏移A);
	//飞溅粒子生成参数.m_Address_KeyOffset_b = f_buf_getAddress(m_排序键值偏移B);
	//飞溅粒子生成参数.m_dim = _iVec3(m_网格分辨率);
	//飞溅粒子生成参数.m_particleCount = m_坐标.m_Mem.m_数量;
	//飞溅粒子生成参数.m_Address_SimParam = f_buf_getAddress(m_解算参数);
	//uint32 合并数量 = num;
	//f_GPU_run计算(m_GPU计算_飞溅粒子排序生成, { num, 1, 1 }, &参数, sizeof(S_PBF_DiffuseCombining_ConstPush));
}

void S_PhysicspPBF::f_排序粒子() {
	uint32 粒子分组数量 = m_坐标.m_Mem.m_数量 / DEF_PBF_GroupSize;
	if (!粒子分组数量) return;
	uvec2* key;
	
	S_PBF_RadixSort_ConstPush 参数{};
	参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
	参数.m_Address_KeyOffset_a = f_buf_getOffsetAddress(m_排序键值偏移A);
	参数.m_Address_KeyOffset_b = f_buf_getOffsetAddress(m_排序键值偏移B);
	参数.m_Address_KeyCount = f_buf_getOffsetAddress(m_排序键值区间数量);
	参数.m_Address_isSwap = f_buf_getOffsetAddress(m_排序跳过交换);

	参数.m_dim = _iVec3(m_网格分辨率);
	参数.m_particleCount = m_粒子数量;

	f_buf_I32_at(m_排序跳过交换) = 1;

	uint32 合并数量 = 粒子分组数量;
	for (uint32 i = 0; i < 32; ++i) {
		
		if (bool(i & 1)) {
			参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序临时键值);
		}
		else {
			参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
		}

		参数.m_Bit = i;

		f_buf_I32_at(m_排序跳过交换) = 0;
		f_GPU_run计算(m_GPU计算_粒子排序, { 粒子分组数量, 1, 1 }, &参数, sizeof(S_PBF_RadixSort_ConstPush));

		if (f_buf_I32_at(m_排序跳过交换) == 0) {
			//continue;
		}


		//auto* key = f_buf_uVec2_ptr(m_排序键值区间数量);
		//for (uint32 k = 0; k < m_排序键值区间数量.m_Mem.m_数量; ++k) {
		//	std::cout << k << " " << key[k].x << " " << key[k].y << " " << (key[k].y & 1 << i) << std::endl;
		//}
		//key = f_buf_uVec2_ptr(m_排序临时键值);
		//for (uint32 k = 0; k < m_排序临时键值.m_Mem.m_数量; ++k) {
		//	std::cout << k << " " << key[k].x << " " << key[k].y << " " << (key[k].y & 1 << i) << std::endl;
		//}

		int32 b = 0;
		S_PBF_MapRange_ConstPush 排序合并{};
		{
			排序合并.m_Bit = 1;
			排序合并.m_groupCount = 粒子分组数量;
			排序合并.m_Address_KeyOffset_a = f_buf_getOffsetAddress(m_排序键值偏移A);
			排序合并.m_Address_KeyOffset_b = f_buf_getOffsetAddress(m_排序键值偏移B);

			uint32 线程数 = 合并数量 - 排序合并.m_Bit;
			for (; b < 32; ++b) {
				
				f_GPU_run计算(m_GPU计算_粒子排序偏移, { 线程数, 1, 1 }, &排序合并, sizeof(S_PBF_MapRange_ConstPush));
				
				f_GPU_run计算(m_GPU计算_粒子排序偏移复制, { 合并数量, 1, 1 }, &排序合并, sizeof(S_PBF_MapRange_ConstPush));

				排序合并.m_Bit <<= 1;
				if (排序合并.m_Bit > 合并数量) {
					break;
				}
				线程数 = 合并数量 - 排序合并.m_Bit;
			}
		}
		
		{
			S_PBF_CombiningSort_ConstPush 合并参数{};
			合并参数.m_Address_IndexKey_a = f_buf_getOffsetAddress(m_排序键值);
			合并参数.m_Address_IndexKey_b = f_buf_getOffsetAddress(m_排序临时键值);
			合并参数.m_Address_KeyOffset = f_buf_getOffsetAddress(m_排序键值偏移A);
			合并参数.m_Address_KeyCount = f_buf_getOffsetAddress(m_排序键值区间数量);

			uint32 o = f_buf_uVec2_ptr(m_排序键值偏移A)[粒子分组数量 - 1].x;
			uint32 on = f_buf_uVec2_ptr(m_排序键值区间数量)[粒子分组数量 - 1].x;
			合并参数.m_secondStart_b = f_buf_uVec2_ptr(m_排序键值偏移A)[粒子分组数量 - 1].x;
			

			uvec2 区间元素数量 = f_buf_uVec2_ptr(m_排序键值区间数量)[0];
			合并参数.m_offset_a = 区间元素数量.x;
			合并参数.m_offset_b = 区间元素数量.y;
			合并参数.m_particleCount = m_粒子数量;


			if (bool(i & 1)) {
				合并参数.m_Address_IndexKey_a = f_buf_getOffsetAddress(m_排序键值);
				合并参数.m_Address_IndexKey_b = f_buf_getOffsetAddress(m_排序临时键值);
			}
			else {
				合并参数.m_Address_IndexKey_a = f_buf_getOffsetAddress(m_排序临时键值);
				合并参数.m_Address_IndexKey_b = f_buf_getOffsetAddress(m_排序键值);
			}
			
			f_GPU_run计算(m_GPU计算_粒子排序合并, { 粒子分组数量, 1, 1 }, &合并参数, sizeof(S_PBF_CombiningSort_ConstPush));
		}
	}
	//return;
	S_PBF_ParticleGrid_ConstPush 网格参数;
	网格参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
	网格参数.m_Address_Particle = f_buf_getOffsetAddress(m_单元粒子索引网格);
	
	网格参数.m_gridOffset = m_域偏移;
	网格参数.m_dim = _iVec3(m_网格分辨率);
	网格参数.m_cellSize = m_网格单元大小;
	网格参数.m_particleCount = m_粒子数量;

	f_GPU_run计算(m_GPU计算_清除粒子在网格索引, m_网格分辨率, &网格参数, sizeof(S_PBF_ParticleGrid_ConstPush));
	f_GPU_run计算(m_GPU计算_粒子在网格索引, { 粒子分组数量, 1, 1 }, &网格参数, sizeof(S_PBF_ParticleGrid_ConstPush));

	//key = f_buf_uVec2_ptr(m_排序临时键值);
	//for (uint32 k = 0; k < m_排序键值.m_Mem.m_数量; ++k) {
	//	std::cout << k << " b " << key[k].x << " " << key[k].y << " " << bool(key[k].y & 1) << std::endl;
	//}

	//key = f_buf_uVec2_ptr(m_排序键值);
	//for (uint32 k = 0; k < m_排序键值.m_Mem.m_数量; ++k) {
	//	std::cout << k << " b " << key[k].x << " " << key[k].y << " " << bool(key[k].y & 1) << std::endl;
	//}

	//auto* gridIndex = f_buf_uVec2_ptr(m_单元粒子索引网格);
	//for (uint32 z = 0; z < m_网格分辨率.z; ++z) {
	//	for (uint32 y = 0; y < m_网格分辨率.y; ++y) {
	//		for (uint32 x = 0; x < m_网格分辨率.z; ++x) {
	//			uint32 offset = f_glsl_CoordToIndex({x,y,z}, m_网格分辨率);
	//			std::cout << "单元粒子索引网格 " << x <<" " << y <<" " << " "<<z << " offset:" << offset << " " << gridIndex[offset].x <<" " << gridIndex[offset].y << std::endl;
	//		}
	//	}
	//}
}

#define GAS_CONSTANT 1000.0
#define REST_DENSITY 1000.0

void S_PhysicspPBF::f_计算力(float32 dt) {
	S_PBF_ParticleForce_ConstPush 参数;
	参数.m_Address_Particle = f_buf_getOffsetAddress(m_坐标);
	参数.m_Address_OldParticle = f_buf_getOffsetAddress(m_前一帧坐标);
	参数.m_Address_Velocity = f_buf_getOffsetAddress(m_速度和年龄);
	参数.m_Address_Acceleration = f_buf_getOffsetAddress(m_加速度);
	参数.m_Address_Delta = f_buf_getOffsetAddress(m_Delta);
	
	参数.m_Address_Mass = f_buf_getOffsetAddress(m_碰撞质量_密度_lambda);
	参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
	参数.m_Address_Grid = f_buf_getOffsetAddress(m_单元粒子索引网格);

	参数.m_Address_SimParam = f_buf_getOffsetAddress(m_解算参数);

	参数.m_Address_RtOb = f_buf_getOffsetAddress(m_计数层->m_光追实例物体);


	参数.m_dim = _iVec3(m_网格分辨率);
	参数.m_cellSize = m_网格单元大小;
	参数.m_particleCount = m_粒子数量;
	参数.m_dt = dt;

	参数.m_min_bound = m_域偏移;
	参数.m_max_bound = m_域偏移 + _Vec3(m_网格分辨率) * m_网格单元大小;
	参数.m_CollisionMeshNum = m_计数层->m_光追实例变换.m_Mem.m_数量;
	
	
	f_GPU_run计算(m_GPU计算_计算密度和压力, { uint32(m_坐标.m_Mem.m_数量 / DEF_PBF_GroupSize), 1, 1 }, &参数, sizeof(S_PBF_ParticleForce_ConstPush));
	
	f_GPU_run计算(m_GPU计算_粒子力计算, { uint32(m_坐标.m_Mem.m_数量) / DEF_PBF_GroupSize, 1, 1 }, &参数, sizeof(S_PBF_ParticleForce_ConstPush));
	

	{
		//uint32 光追描述集数量 = f_ob_get光追加速结构描述集数量(m_计数层->m_光追描述集);
		//if (光追描述集数量) {
			m_碰撞参数.m_参数槽[0] = m_计数层->m_光追描述集;
			m_碰撞参数.m_参数类型[0] = E_板载缓存类型::e_光追BVH;
			m_碰撞参数.m_绑定位置[0] = DEF_BINDING_topLAS;
			m_碰撞参数.m_绑定数量[0] = f_ob_get光追加速结构描述集数量(m_计数层->m_光追描述集);

			m_碰撞参数.m_参数槽[1] = f_buf_getGlobal().m_场景物体网格属性;
			m_碰撞参数.m_参数类型[1] = E_板载缓存类型::e_SSBO;
			m_碰撞参数.m_绑定位置[1] = DEF_BINDING_Ray_ObMesh;
			m_碰撞参数.m_绑定数量[1] = 1;

			f_df_upGPU参数(m_设备.m_逻辑设备.设备, m_GPU计算_粒子碰撞更新->m_GPU参数set, m_碰撞参数, false);
			f_GPU_run计算(m_GPU计算_粒子碰撞更新, { uint32(m_坐标.m_Mem.m_数量) / DEF_PBF_GroupSize, 1, 1 }, &参数, sizeof(S_PBF_ParticleForce_ConstPush));
		//}
	}
	
	f_GPU_run计算(m_GPU计算_粒子粘力, { uint32(m_坐标.m_Mem.m_数量) / DEF_PBF_GroupSize, 1, 1 }, &参数, sizeof(S_PBF_ParticleForce_ConstPush));
	
	return;



	if(!m_坐标.m_Mem.m_数量) return;
	//vec2* 质量密度 = f_buf_Vec2_ptr(m_质量密度);
	vec3* 质量密度 = f_buf_Vec3_ptr(m_碰撞质量_密度_lambda);

	auto* ValueKey = f_buf_uVec2_ptr(m_排序键值);
	uvec2* GridOffset = f_buf_uVec2_ptr(m_单元粒子索引网格);
	vec3* particle = f_buf_Vec3_ptr(m_坐标);
	vec3* acceleration = f_buf_Vec3_ptr(m_加速度);
	vec4* velocity = f_buf_Vec4_ptr(m_速度和年龄);
	
	float32* 压力 = f_buf_F32_ptr(m_质量);
	int32 DEF_R = 1;


	auto simP = f_buf_PBF解算参数_ptr(m_解算参数)[0];
	float h = simP.radius * 2;

	{
		//for (int32 k = 0; k < m_排序键值.m_Mem.m_数量; ++k) {
		//	std::cout<< ValueKey[k].x <<" "<< ValueKey[k].y<<"\n";
		//}

		/*static uint32 id = 0;
		if(id >= m_粒子数量) id = 0;
		vec3 currentParticle = particle[id];
		ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[id].y, m_网格分辨率);

		for (int z = -DEF_R; z <= DEF_R; ++z) {
			for (int y = -DEF_R; y <= DEF_R; ++y) {
				for (int x = -DEF_R; x <= DEF_R; ++x) {
					ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
					coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);

					uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);
					uvec2 NeightOffset = GridOffset[neighborCoordIndex];
					if (NeightOffset.x >= 0xffffffff) continue;

					for (uint i = 0; i < NeightOffset.y; ++i) {
						uint vertIndex = ValueKey[NeightOffset.x + i].x;
						//if (vertIndex == id) continue;

						vec3 NeightParticle = particle[vertIndex];
						vec3 p = currentParticle - NeightParticle;
						float r = length(p);

						particle[vertIndex] = {};
					}
				}
			}
		}
		++id;
		return;*/
	}

#pragma omp parallel for
		for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {
			
			ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[id].y, m_网格分辨率);
			uint32 index = ValueKey[id].x;
			vec3 currentParticle = particle[id];

			质量密度[id].y = 0;

			for (int z = -DEF_R; z <= DEF_R; ++z) {
				for (int y = -DEF_R; y <= DEF_R; ++y) {
					for (int x = -DEF_R; x <= DEF_R; ++x) {
						ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
						coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);

						uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);
						uvec2 NeightOffset = GridOffset[neighborCoordIndex];
						if (NeightOffset.x >= 0xffffffff) continue;

						for (uint i = 0; i < NeightOffset.y; ++i) {
							//uint vertIndex = NeightOffset.x + i;
							uint vertIndex = ValueKey[NeightOffset.x + i].x;
							if (vertIndex == index) continue;

							vec3 NeightParticle = particle[vertIndex];
							vec3 p = currentParticle - NeightParticle;
							float r = length(p);

							// 更新粒子i的密度
							if (r > 1e-7 && r < m_网格单元大小) {
								float w = Poly6((r), h);

								if (质量密度[id].x <= 0) {
									质量密度[id].y += w * 1;
								}
								else {
									//质量密度[vertIndex].x;
									质量密度[id].y += w * 1000;
								}
								

								//质量密度[index].y += 1 * kernel(r, m_网格单元大小);
							}
						}
					}
				}
			}
		}

//
//#pragma omp parallel for
//		for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {
//			// 假设气体常数为k
//			压力[id] = 1 * 质量密度[id].y;
//		}
//
		
#pragma omp parallel for
		for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {
			vec3 currentParticle = particle[id];
			ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[id].y, m_网格分辨率);

			vec3 force = { 0.0, 0.0, 0.0 };
			vec3 accel = { 0.0, 0.0, 0.0 };
			vec3 viscosity_force{};
			float h2 = m_网格单元大小 * m_网格单元大小;
			float c = 1.4;
			float gamma = 1.4;
			float rhoi = 质量密度[id].y;
			float lambda = 0;

			float C = max(rhoi / simP.rest_density - 1, 0);
			if (C != 0) {
				lambda;
				float sum_grad_C2 = 0;
				vec3 gradC_i = {};

				for (int z = -DEF_R; z <= DEF_R; ++z) {
					for (int y = -DEF_R; y <= DEF_R; ++y) {
						for (int x = -DEF_R; x <= DEF_R; ++x) {
							ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
							coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);

							uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);
							uvec2 NeightOffset = GridOffset[neighborCoordIndex];
							if (NeightOffset.x >= 0xffffffff) continue;

							for (uint i = 0; i < NeightOffset.y; ++i) {
								//uint vertIndex = NeightOffset.x + i;
								uint vertIndex = ValueKey[NeightOffset.x + i].x;
								if (vertIndex == id) continue;

								vec3 NeightParticle = particle[vertIndex];
								vec3 p = currentParticle - NeightParticle;
								float r = length(p);

								// 更新粒子i的密度
								if (r > 1e-7 && r < simP.radius) {
									if (质量密度[id].x <= 0) {
										vec3 gradC_j = poly6KernelGrad(p, r, h) * (-1 / simP.rest_density);
										sum_grad_C2 += f_squaredNorm(gradC_j);
										gradC_i -= gradC_j;
									}
									else {
										vec3 gradC_j = poly6KernelGrad(p, r, h) * (-质量密度[id].x / simP.rest_density);
										sum_grad_C2 += f_squaredNorm(gradC_j);
										gradC_i -= gradC_j;
									}
								}
							}
						}
					}
				}

				sum_grad_C2 += f_squaredNorm(gradC_i);
				lambda = -C / (sum_grad_C2 + 1e-6);
			}
			else {
				lambda = 0;
			}
			质量密度[id].y = lambda;


			//for (int z = -DEF_R; z <= DEF_R; ++z) {
			//	for (int y = -DEF_R; y <= DEF_R; ++y) {
			//		for (int x = -DEF_R; x <= DEF_R; ++x) {
			//			ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
			//			coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);
			//
			//			uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);
			//			uvec2 NeightOffset = GridOffset[neighborCoordIndex];
			//			if (NeightOffset.x >= 0xffffffff) continue;
			//
			//			for (uint i = 0; i < NeightOffset.y; ++i) {
			//				uint vertIndex = NeightOffset.x + i;
			//				//if (vertIndex == id) continue;
			//
			//				vec3 NeightParticle = particle[ValueKey[vertIndex].x];
			//				vec3 p = currentParticle - NeightParticle;
			//				float r = length(p);
			//
			//				if (r < m_网格单元大小) {
			//					float q = r / m_网格单元大小;
			//					float u = 1 - q;
			//					float wk = u / (h2 * h2 * h2);
			//					float dwk = -2 * u / (h2*h2*r);
			//
			//					float rhoj = 质量密度[vertIndex].y;
			//					vec3 vj = velocity[id] - velocity[vertIndex];
			//
			//					float mj = 1;
			//					float pj = 压力[vertIndex];
			//					
			//
			//					accel.x += -mj * (M_PI / (质量密度[id].y * 质量密度[id].y) + pj / (rhoj * rhoj)) * dwk * p.x + gamma * mj * c * c * (rhoi * rhoj) * wk * vj.x;
			//					accel.y += -mj * (M_PI / (质量密度[id].y * 质量密度[id].y) + pj / (rhoj * rhoj)) * dwk * p.y + gamma * mj * c * c * (rhoi * rhoj) * wk * vj.y;
			//					accel.z += -mj * (M_PI / (质量密度[id].y * 质量密度[id].y) + pj / (rhoj * rhoj)) * dwk * p.z + gamma * mj * c * c * (rhoi * rhoj) * wk * vj.z;
			//				}
			//			}
			//		}
			//	}
			//}
			//
			//accel += vec3{0,-9.8,0} * 质量密度[id].y;
			//
			//velocity[id] += accel * 0.01;
			//acceleration[id] += velocity[id] * 0.01;
		}
		

#pragma omp parallel for
		for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {

			ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[id].y, m_网格分辨率);
			uint32 index = ValueKey[id].x;
			vec3 currentParticle = particle[id];

			vec3 corr{};

			for (int z = -DEF_R; z <= DEF_R; ++z) {
				for (int y = -DEF_R; y <= DEF_R; ++y) {
					for (int x = -DEF_R; x <= DEF_R; ++x) {
						ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
						coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);

						uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);
						uvec2 NeightOffset = GridOffset[neighborCoordIndex];
						if (NeightOffset.x >= 0xffffffff) continue;

						for (uint i = 0; i < NeightOffset.y; ++i) {
							//uint vertIndex = NeightOffset.x + i;
							uint vertIndex = ValueKey[NeightOffset.x + i].x;
							if (vertIndex == index) continue;

							vec3 NeightParticle = particle[vertIndex];
							vec3 p = currentParticle - NeightParticle;
							float r = length(p);

							// 更新粒子i的密度
							if (r > 1e-7 && r < m_网格单元大小) {
								float w = Poly6((r), h);

								if (质量密度[id].x <= 0) {
									const vec3 gradC_j = poly6KernelGrad(p, r, h) * (-1 / simP.rest_density);
									corr -= gradC_j * (质量密度[id].y + 质量密度[vertIndex].y);
								}
								else {
									const vec3 gradC_j = poly6KernelGrad(p, r, h) * (-质量密度[id].x / simP.rest_density);
									corr -= gradC_j * 质量密度[id].y;
								}
							}
						}
					}
				}
			}
		}
	return;

#pragma omp parallel for
	for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {
		ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[id].y, m_网格分辨率);
		uint32 index = ValueKey[id].x;
		vec3 currentParticle = particle[index];

		vec3 pressure = vec3{};
		vec3 accel = {};
		float32 rho = 0;
		float32 h = m_网格单元大小;

		//int c = 0;
		for (int z = -1; z <= 1; ++z) {
			for (int y = -1; y <= 1; ++y) {
				for (int x = -1; x <= 1; ++x) {
					ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
					coord = vec_Min(_iVec3(m_网格分辨率) - 1, coord);
					uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), m_网格分辨率);

					uvec2 NeightOffset = GridOffset[neighborCoordIndex];
					if (NeightOffset.x >= 0xffffffff) continue;


					for (uint i = 0; i < NeightOffset.y; ++i) {
						uint vertIndex = ValueKey[ NeightOffset.x + i ].x;
						if (vertIndex == index) continue;

						//vec3 NeightParticle = particle[ValueKey[NeightOffset.x + i].x];
						vec3 NeightParticle = particle[vertIndex];
						vec3 p = currentParticle - NeightParticle;
						float r = length(p);

						if (r < m_网格单元大小) {
							p = normalize(p);
							float s = 1 / h;
							//s = 1;
							auto w = f_W_Poly6(r*s, m_网格单元大小*s);
							w = -0.1 * ((质量密度[index].y + 质量密度[vertIndex].y - 2*1000) / 2) * w;
							pressure += p * w * m_网格单元大小;
						}

					}
				}
			}
		}

		//if (c == 0) 
		//	pressure = vec3{0, 0, 0};
		//accel = pressure;
		//accel *= 0.1;
		
		accel += vec3{0,-0.98,0} *dt;
		accel += pressure * dt;
		
		acceleration[index] += accel * dt;
	}

//#pragma omp parallel for
//	for (int32 id = 0; id < m_坐标.m_Mem.m_数量; ++id) {
//		particle[id] += acceleration[id];
//	}

}

void S_PhysicspPBF::f_生成飞溅粒子(float32 dt) {
	uvec2* key;

	S_PBF_DiffuseCombining_ConstPush 参数{};
	参数.m_Address_Acceleration = f_buf_getOffsetAddress(m_速度和年龄);
	参数.m_Address_Mass = f_buf_getOffsetAddress(m_碰撞质量_密度_lambda);

	参数.m_Address_IndexKey_a = f_buf_getOffsetAddress(m_排序临时键值);
	参数.m_Address_IndexKey_b = f_buf_getOffsetAddress(m_飞溅粒子排序键值);
	参数.m_Address_KeyOffset_a = f_buf_getOffsetAddress(m_排序键值偏移A);
	参数.m_Address_KeyOffset_b = f_buf_getOffsetAddress(m_排序键值偏移B);
	参数.m_Address_KeyCount = f_buf_getOffsetAddress(m_排序键值区间数量);

	参数.m_dim = _iVec3(m_网格分辨率);
	参数.m_particleCount = m_坐标.m_Mem.m_数量;
	
	参数.m_Address_SimParam = f_buf_getOffsetAddress(m_解算参数);
	
	//uint32 粒子数量 = m_坐标.m_Mem.m_数量;
	if(m_速度和年龄.m_Mem.m_数量 <= 0) return;


	//飞溅粒子生成
	uint32 num = m_坐标.m_Mem.m_数量 / DEF_PBF_GroupSize;
	uint32 合并数量 = num;
	f_GPU_run计算(m_GPU计算_飞溅粒子生成排序键值, { num, 1, 1 }, &参数, sizeof(S_PBF_DiffuseCombining_ConstPush));
	

	参数.m_Bit = 1;
	uint32 线程数 = num - 参数.m_Bit;
	for (int32 b = 0; b < 32; ++b) {
		f_GPU_run计算(m_GPU计算_飞溅粒子排序偏移, { 线程数, 1, 1 }, &参数, sizeof(S_PBF_DiffuseCombining_ConstPush));
		
		f_GPU_run计算(m_GPU计算_飞溅粒子排序偏移复制, { num, 1, 1 }, &参数, sizeof(S_PBF_DiffuseCombining_ConstPush));

		参数.m_Bit <<= 1;
		if (参数.m_Bit > 合并数量) {
			break;
		}
		线程数 = 合并数量 - 参数.m_Bit;
	}
	
	
	f_GPU_run计算(m_GPU计算_飞溅粒子排序合并, { num, 1, 1 }, &参数, sizeof(S_PBF_DiffuseCombining_ConstPush));
	//key = f_buf_uVec2_ptr(m_排序临时键值);
	//for (uint32 k = 0; k < m_排序临时键值.m_Mem.m_数量; ++k) {
	//	std::cout << k << " *** 排序键值 索引:" << key[k].x << " 数量:" << key[k].y << std::endl;
	//}
	

	auto* 偏移 = f_buf_uVec2_ptr(m_排序键值偏移A);
	uint32 新产生飞溅粒子数量 = 偏移[m_排序键值偏移A.m_Mem.m_数量 - 1].x;
	m_有效飞溅粒子数量 = m_已有发射粒子索引数量A + 新产生飞溅粒子数量 * DEF_PBF_SplashNum;

	if (m_飞溅坐标.m_Mem.m_数量 < m_有效飞溅粒子数量) {
		uint32 总飞溅粒子数量 = (m_已有飞溅粒子数量 + 新产生飞溅粒子数量) * DEF_PBF_SplashNum;
		f_bm_resize(m_飞溅坐标, 总飞溅粒子数量);
		f_bm_resize(m_飞溅速度, 总飞溅粒子数量);
		f_bm_resize(m_飞溅寿命, 总飞溅粒子数量);

		//m_已有飞溅粒子索引数量 = m_飞溅粒子发射排序键值.m_Mem.m_数量;
		uint32 飞溅粒子组数量 = (m_有效飞溅粒子数量 + DEF_PBF_GroupSize) / DEF_PBF_GroupSize;
		uint32 飞溅粒子对齐数量 = 飞溅粒子组数量 * DEF_PBF_GroupSize;
		f_bm_resize(m_飞溅粒子发射排序键值A, 飞溅粒子对齐数量);
		f_bm_resize(m_飞溅粒子发射排序键值B, 飞溅粒子对齐数量);
		//assert(m_已有发射粒子索引数量 < 飞溅粒子对齐数量);
	}
	
	

	S_PBF_GenDiffuse_ConstPush 粒子计算参数{};
	粒子计算参数.m_Address_Particle = f_buf_getOffsetAddress(m_坐标);
	粒子计算参数.m_Address_Acceleration = f_buf_getOffsetAddress(m_速度和年龄);
	粒子计算参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_飞溅粒子排序键值);
	
	粒子计算参数.m_Address_SplashParticle = f_buf_getOffsetAddress(m_飞溅坐标);
	粒子计算参数.m_Address_SplashAcceleration = f_buf_getOffsetAddress(m_飞溅速度);
	粒子计算参数.m_Address_SplashLifetime = f_buf_getOffsetAddress(m_飞溅寿命);
	粒子计算参数.m_Address_SplashIndexKey = f_buf_getOffsetAddress(m_飞溅粒子发射排序键值A);
	粒子计算参数.m_Address_SimParam = f_buf_getOffsetAddress(m_解算参数);

	粒子计算参数.m_cellSize = m_网格单元大小;
	粒子计算参数.m_dim = _iVec3(m_网格分辨率);
	粒子计算参数.m_gridOffset = m_域偏移;
	粒子计算参数.m_dt = dt;
	粒子计算参数.m_particleCount = 新产生飞溅粒子数量;
	粒子计算参数.m_particleOffset = m_已有发射粒子索引数量A ;
	//粒子计算参数.m_particleOffset = 0;
	粒子计算参数.m_particleReuse = (m_已有发射粒子索引数量A + m_已有发射粒子索引数量B);
	//粒子计算参数.m_particleReuse = 0;

	粒子计算参数.m_min_bound = m_域偏移;
	粒子计算参数.m_max_bound = m_域偏移 + _Vec3(m_网格分辨率) * m_网格单元大小;
	std::cout << " m_particleOffset： " << 粒子计算参数.m_particleOffset << " m_particleReuse: " << 粒子计算参数.m_particleReuse << " " << m_有效飞溅粒子数量 << "\n";
	
	//uint32* index = f_buf_UI32_ptr(m_飞溅粒子发射排序键值A);
	//for (uint32 k = 0; k < 飞溅粒子对齐数量; ++k) {
	//	std::cout << k << " 排序键值 索引:" << index[k] << std::endl;
	//}
	f_GPU_run计算(m_GPU计算_计算飞溅粒子生成, { 新产生飞溅粒子数量, 1, 1 }, &粒子计算参数, sizeof(S_PBF_GenDiffuse_ConstPush));
	


	粒子计算参数.m_Address_IndexKey = f_buf_getOffsetAddress(m_排序键值);
	粒子计算参数.m_Address_Grid = f_buf_getOffsetAddress(m_单元粒子索引网格);

	粒子计算参数.m_Address_SplashParticle = f_buf_getOffsetAddress(m_飞溅坐标);
	粒子计算参数.m_Address_SplashAcceleration = f_buf_getOffsetAddress(m_飞溅速度);
	粒子计算参数.m_Address_SplashLifetime = f_buf_getOffsetAddress(m_飞溅寿命);
	//粒子计算参数.m_particleCount = m_已有粒子数量;
	m_已有飞溅粒子数量 += 新产生飞溅粒子数量;

	f_GPU_run计算(m_GPU计算_计算飞溅粒子运动, { m_有效飞溅粒子数量, 1, 1 }, &粒子计算参数, sizeof(S_PBF_GenDiffuse_ConstPush));

}

void S_PhysicspPBF::f_发射飞溅粒子() {
	S_PBF_DiffuseEmission_ConstPush 粒子发射参数{};
	
	uint32 飞溅粒子组数量 = (m_已有飞溅粒子数量 * DEF_PBF_SplashNum + DEF_PBF_GroupSize) / DEF_PBF_GroupSize;
	uint32 飞溅粒子对齐数量 = 飞溅粒子组数量 * DEF_PBF_GroupSize;
	
	if (m_发射飞溅粒子排序键值偏移A.m_Mem.m_数量 < 飞溅粒子组数量) {
		f_bm_resize(m_飞溅粒子排序区间数量, 飞溅粒子组数量);
		f_bm_resize(m_发射飞溅粒子排序键值偏移A, 飞溅粒子组数量);
		f_bm_resize(m_发射飞溅粒子排序键值偏移B, 飞溅粒子组数量);
	}
	

	粒子发射参数.m_Address_SplashLifetime = f_buf_getOffsetAddress(m_飞溅寿命);
	粒子发射参数.m_particleCount = m_飞溅坐标.m_Mem.m_数量;

	粒子发射参数.m_Address_IndexKey_a = f_buf_getOffsetAddress(m_飞溅粒子发射排序键值A);
	粒子发射参数.m_Address_IndexKey_b = f_buf_getOffsetAddress(m_飞溅粒子发射排序键值B);
	粒子发射参数.m_Address_KeyCount = f_buf_getOffsetAddress(m_飞溅粒子排序区间数量);
	
	粒子发射参数.m_Address_KeyOffset_a = f_buf_getOffsetAddress(m_发射飞溅粒子排序键值偏移B);
	粒子发射参数.m_Address_KeyOffset_b = f_buf_getOffsetAddress(m_发射飞溅粒子排序键值偏移A);
	粒子发射参数.m_Address_SimParam = f_buf_getOffsetAddress(m_解算参数);
	

	f_GPU_run计算(m_GPU计算_飞溅粒子发射排序, { 飞溅粒子组数量, 1, 1 }, &粒子发射参数, sizeof(S_PBF_DiffuseEmission_ConstPush));
	//return;
	//uint32* index = f_buf_UI32_ptr(m_飞溅粒子发射排序键值B);
	//for (uint32 k = 0; k < 飞溅粒子对齐数量; ++k) {
	//	std::cout << k << " 排序键值 索引:" << index[k] << std::endl;
	//}


	粒子发射参数.m_Bit = 1;
	uint32 线程数 = 飞溅粒子组数量 - 粒子发射参数.m_Bit;
	for (int32 b = 0; b < 32; ++b) {
		f_GPU_run计算(m_GPU计算_飞溅粒子发射排序偏移, { 线程数, 1, 1 }, &粒子发射参数, sizeof(S_PBF_DiffuseEmission_ConstPush));

		f_GPU_run计算(m_GPU计算_飞溅粒子发射排序偏移复制, { 飞溅粒子组数量, 1, 1 }, &粒子发射参数, sizeof(S_PBF_DiffuseEmission_ConstPush));

		if (粒子发射参数.m_Bit > 粒子发射参数.m_particleCount) {
			break;
		}

		粒子发射参数.m_Bit <<= 1;
		if (粒子发射参数.m_Bit > 飞溅粒子组数量 || 粒子发射参数.m_Bit > 粒子发射参数.m_particleCount) {
			break;
		}
		线程数 = 飞溅粒子组数量 - 粒子发射参数.m_Bit;
	}
	

	auto* 偏移 = f_buf_uVec2_ptr(m_发射飞溅粒子排序键值偏移A);
	m_已有发射粒子索引数量A = 偏移[m_发射飞溅粒子排序键值偏移A.m_Mem.m_数量 - 1].x;
	m_已有发射粒子索引数量B = 偏移[m_发射飞溅粒子排序键值偏移A.m_Mem.m_数量 - 1].y;

	粒子发射参数.m_secondStart_b = m_已有发射粒子索引数量A;
	//return;
	f_GPU_run计算(m_GPU计算_飞溅粒子发射排序合并, { 飞溅粒子组数量, 1, 1 }, &粒子发射参数, sizeof(S_PBF_DiffuseEmission_ConstPush));
}

void S_PhysicspPBF::f_更新粒子() {
}

























static void f_构建物理体体素坐标(S_PhysicspPBF& pbf
								, S_物理体* 物理体
								, std::vector<vec3>& 体素坐标
								, std::vector<vec3>& 体素速度
	, std::vector<vec3>& 体素质量
	, std::vector<S_ParticleAttr>& 类型和状态
								) {
	switch (物理体->m_物理体类型) {
		case E_物理体类型::E_物理体_刚体: {
			break;
		}
		case E_物理体类型::E_物理体_柔体: {
			break;
		}
		case E_物理体类型::E_物理体_布料: {
			break;
		}
		case E_物理体类型::E_物理体_流入: {
			auto* ob = ((S_物体*)(物理体->m_Data));
			if(!ob) break;

			S_粒子系统配置* parsys = f_ob_fromParticle(ob);

			体素坐标.resize(parsys->m_Count, {});
			体素速度.resize(parsys->m_Count, {});
			体素质量.resize(parsys->m_Count, {1,1});
			类型和状态.resize(parsys->m_Count, f_物体类型和状态(E_物理体类型::E_物理体_流入, DEF_ParticleState_disable, 0));

			pbf.m_流入[物理体->m_Name] = 物理体;
			break;
		}
		default: {
			auto* ob = ((S_物体*)物理体->m_几何体->m_绑定网格物体);
			if (!ob) break;

			auto me = f_ob_getMesh((S_物体*)物理体->m_几何体->m_绑定网格物体, E_物体网格元素类型::e_MT_面);

			f_fromMesh创建体素(me, f_ob_get变换矩阵(ob, ob->m_实例ID), pbf.m_网格单元大小 * 0.5, 体素坐标);

			体素速度.resize(体素坐标.size(), {});
			体素质量.resize(体素坐标.size(), { 1, 1 });
			类型和状态.resize(体素坐标.size(), f_物体类型和状态(E_物理体类型::E_物理体_流体, DEF_ParticleState_enable, 999999999));
			pbf.m_流体[物理体->m_Name] = 物理体;
			break;
		}


	}
}

static void f_物理体储存(S_PhysicspPBF& pbf, S_物理体* 物理体) {
	switch (物理体->m_物理体类型) {
		case E_物理体类型::E_物理体_静态: {
			break;
		}
		case E_物理体类型::E_物理体_刚体: {
			break;
		}
		case E_物理体类型::E_物理体_柔体: {
			break;
		}
		case E_物理体类型::E_物理体_布料: {
			break;
		}
		case E_物理体类型::E_物理体_流入: {
			break;
		}
	}
}

static void f_重置飞溅粒子(S_PhysicspPBF& pbf) {
	f_bm_resize(pbf.m_飞溅坐标, 0);
	f_bm_resize(pbf.m_飞溅速度, 0);
	f_bm_resize(pbf.m_飞溅寿命, 0);
	f_bm_resize(pbf.m_飞溅粒子排序键值, 0);

	f_bm_resize(pbf.m_飞溅粒子发射排序键值A, 0);
	f_bm_resize(pbf.m_飞溅粒子发射排序键值B, 0);
	f_bm_resize(pbf.m_飞溅粒子排序区间数量, 0);
	f_bm_resize(pbf.m_发射飞溅粒子排序键值偏移A, 0);
	f_bm_resize(pbf.m_发射飞溅粒子排序键值偏移B, 0);


	pbf.m_已有飞溅粒子数量 = 0;
	pbf.m_已有发射粒子索引数量A = 0;
	pbf.m_已有发射粒子索引数量B = 0;
}


S_PhysicspPBF* f_pbf_创建PBF(S_设备环境& ctx) {
	S_PhysicspPBF* pbf = new S_PhysicspPBF(ctx);

	pbf->m_坐标 = f_bm_alloc(f_buf_getGlobal().g_MPM_坐标, 0);
	pbf->m_前一帧坐标 = f_bm_alloc(f_buf_getGlobal().g_PHY_前一帧坐标, 0);
	pbf->m_质量 = f_bm_alloc(f_buf_getGlobal().g_PHY_压力, 0);
	pbf->m_速度和年龄 = f_bm_alloc(f_buf_getGlobal().g_PHY_速度和年龄, 0);
	pbf->m_加速度 = f_bm_alloc(f_buf_getGlobal().g_MPM_速度梯度, 0);
	pbf->m_碰撞质量_密度_lambda = f_bm_alloc(f_buf_getGlobal().g_MPM_密度_lambda, 0);
	pbf->m_Delta = f_bm_alloc(f_buf_getGlobal().m_Delta, 0);
	pbf->m_粒子类型状态 = f_bm_alloc(f_buf_getGlobal().g_PHY_粒子类型和状态, 0);

	pbf->m_排序键值 = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值, 0);
	pbf->m_排序临时键值 = f_bm_alloc(f_buf_getGlobal().g_PHY_排序临时键值, 0);
	pbf->m_排序键值偏移A = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值偏移A, 0);
	pbf->m_排序键值偏移B = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值偏移B, 0);
	pbf->m_排序键值区间数量 = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值数量, 0);

	pbf->m_飞溅坐标 = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅坐标, 0);
	pbf->m_飞溅速度 = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅速度, 0);
	pbf->m_飞溅寿命 = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅粒子寿命, 0);
	pbf->m_飞溅粒子排序键值 = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅排序键值, 0);
	pbf->m_排序跳过交换 = f_bm_alloc(f_buf_getGlobal().m_I32动态属性, 1);
	
	pbf->m_飞溅粒子发射排序键值A = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅粒子发射排序键值, 0);
	pbf->m_飞溅粒子发射排序键值B = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅粒子发射排序键值, 0);
	pbf->m_飞溅粒子排序区间数量 = f_bm_alloc(f_buf_getGlobal().g_PHY_飞溅粒子发射区间数量, 0);
	pbf->m_发射飞溅粒子排序键值偏移A = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值偏移A, 0);
	pbf->m_发射飞溅粒子排序键值偏移B = f_bm_alloc(f_buf_getGlobal().g_PHY_排序键值偏移B, 0);
	
	pbf->m_力 = f_bm_alloc(f_buf_getGlobal().g_PHY_物理力, 0);

	pbf->m_单元粒子索引网格 = f_bm_alloc(f_buf_getGlobal().g_PHY_粒子网格索引, 0);
	pbf->m_解算参数 = f_bm_alloc(f_buf_getGlobal().g_PHY_PBF参数, 1);

	

	f_pbf_初始化解算参数(*f_buf_PBF解算参数_ptr(pbf->m_解算参数));

	return pbf;
}

void f_pbf_销毁PBF(S_PhysicspPBF* pbf) {
	delete pbf;
}

void f_pbf_重构(S_PhysicspPBF& pbf) {
	f_bm_resize(pbf.m_坐标, 0);
	f_bm_resize(pbf.m_质量, 0);
	f_bm_resize(pbf.m_速度和年龄, 0);
	f_bm_resize(pbf.m_粒子类型状态, 0);
	
	f_bm_resize(pbf.m_加速度, 0);
	f_bm_resize(pbf.m_碰撞质量_密度_lambda, 0);
	f_bm_resize(pbf.m_Delta, 0);


	f_重置飞溅粒子(pbf);
	
	f_ob_clear(&pbf);
	pbf.m_物理体.clear();
	pbf.m_流入.clear();
	pbf.m_流体.clear();
	pbf.m_刚体.clear();
	pbf.m_静态.clear();

	pbf.m_粒子添加偏移 = 0;
	pbf.m_粒子数量 = 0;
}

void f_pbf_设置网格维度(S_PhysicspPBF& pbf, const vec3& 网格大小, const vec3& 域偏移, float32 单元大小) {
	
	pbf.m_域偏移 = 域偏移 - (网格大小 / 2);
	pbf.m_网格单元大小 = 单元大小;
	pbf.m_网格分辨率 = _uVec3(网格大小 / 单元大小);
	

	f_buf_PBF解算参数_ptr(pbf.m_解算参数)[0].radius = pbf.m_网格单元大小*0.33;
	f_bm_resize(pbf.m_单元粒子索引网格, pbf.m_网格分辨率.x * pbf.m_网格分辨率.y * pbf.m_网格分辨率.z);
	
} 

void f_pbf_添加物理体(S_PhysicspPBF& pbf, S_PhyBodyArray* body) {
	pbf.m_碰撞物体.clear();

	for (uint32 i = 0; i < body->count; ++i) {
		auto& 物理体 = body->ptr_userData[i];

		switch (物理体->m_物理体类型) {
			case E_物理体类型::E_物理体_静态: {
				auto* ob = ((S_物体*)物理体->m_几何体->m_绑定网格物体);
				if (!ob) break;

				pbf.m_碰撞物体.push_back(ob);
				pbf.m_静态[物理体->m_Name] = 物理体;
				break;
			}
			default: {
				std::vector<vec3> 体素坐标;
				std::vector<vec3> 体素加速度;
				std::vector<vec4> 体素速度;
				std::vector<vec3> 体素质量;
				std::vector<S_ParticleAttr> 类型和状态;
				f_构建物理体体素坐标(pbf, 物理体, 体素坐标, 体素加速度, 体素质量, 类型和状态);

				体素速度.resize(体素坐标.size());

				f_buf_push_back(pbf.m_坐标, 体素坐标);
				f_buf_push_back(pbf.m_加速度, 体素加速度);
				f_buf_push_back(pbf.m_速度和年龄, 体素速度);
				f_buf_push_back(pbf.m_碰撞质量_密度_lambda, 体素质量);
				f_buf_push_back(pbf.m_粒子类型状态, 类型和状态);

				物理体->m_粒子偏移和数量.x = pbf.m_粒子添加偏移;
				物理体->m_粒子偏移和数量.y = 体素坐标.size();
				pbf.m_粒子添加偏移 += 物理体->m_粒子偏移和数量.y;
				break;
			}
		}

		f_ob_insert(&pbf, 物理体, -1);
		pbf.m_物理体[物理体->m_Name] = 物理体;
	}
	pbf.m_粒子数量 = pbf.m_坐标.m_Mem.m_数量;



	uint32 体素批次_数量 = uint32(pbf.m_坐标.m_Mem.m_数量 / DEF_PBF_GroupSize) + 1;
	uint32 粒子数量 = 体素批次_数量 * DEF_PBF_GroupSize;
	std::vector<vec3> 体素坐标(粒子数量 - pbf.m_坐标.m_Mem.m_数量);
	std::vector<vec3> 体素加速度(粒子数量 - pbf.m_坐标.m_Mem.m_数量);
	std::vector<vec4> 体素速度(粒子数量 - pbf.m_坐标.m_Mem.m_数量);
	std::vector<vec2> 体素密度(粒子数量 - pbf.m_坐标.m_Mem.m_数量, { 1, 0 });
	std::vector<S_ParticleAttr> 体素状态(粒子数量 - pbf.m_坐标.m_Mem.m_数量, f_物体类型和状态(E_物理体类型::E_物理体_空, 0));
	
	f_buf_push_back(pbf.m_坐标, 体素坐标);
	f_buf_push_back(pbf.m_加速度, 体素加速度);
	f_buf_push_back(pbf.m_粒子类型状态, 体素状态);
	f_buf_push_back(pbf.m_速度和年龄, 体素速度);

	f_bm_resize(pbf.m_碰撞质量_密度_lambda, 粒子数量);
	f_bm_resize(pbf.m_排序键值区间数量, 粒子数量);


	f_bm_resize(pbf.m_排序临时键值, pbf.m_坐标.m_Mem.m_数量);
	f_bm_resize(pbf.m_排序键值, pbf.m_坐标.m_Mem.m_数量);
	f_bm_resize(pbf.m_排序键值偏移A, 体素批次_数量);
	f_bm_resize(pbf.m_排序键值偏移B, 体素批次_数量);
	f_bm_resize(pbf.m_排序键值区间数量, 体素批次_数量);
	

	f_bm_resize(pbf.m_质量, 粒子数量);
	f_bm_resize(pbf.m_前一帧坐标, 粒子数量);
	f_bm_resize(pbf.m_Delta, 粒子数量);

	//float λ = 0;

	f_bm_resize(pbf.m_飞溅粒子排序键值, 粒子数量);
	f_bm_resize(pbf.m_飞溅坐标, 0);
	f_bm_resize(pbf.m_飞溅速度, 0);
	f_bm_resize(pbf.m_飞溅寿命, 0);
	 
	pbf.m_已有飞溅粒子数量 = 0;


	f_ob_构建底层层光追加速结构(pbf.m_碰撞物体);

} 

void f_pbf_重置(S_PhysicspPBF& pbf) {
	uint32 num = pbf.m_子物体.size();
	auto* s = pbf.m_子物体.data();

	for (uint32 i = 0; i < num; ++i) {
		S_物理体* 物理体 = dynamic_cast<S_物理体*>(s[i]);

		std::vector<vec3> 体素坐标;
		std::vector<vec3> 体素速度;
		std::vector<vec3> 体素质量;
		std::vector<S_ParticleAttr> 类型和状态;
		f_构建物理体体素坐标(pbf, 物理体, 体素坐标, 体素速度, 体素质量, 类型和状态);

		auto* p = f_buf_Vec3_ptr(pbf.m_坐标);
		auto* v = f_buf_Vec3_ptr(pbf.m_加速度);
		auto* vm = f_buf_Vec4_ptr(pbf.m_速度和年龄);
		auto* m = f_buf_F32_ptr(pbf.m_质量);
		auto* 粒子属性 = f_bm_ptr<S_ParticleAttr>(pbf.m_粒子类型状态);
		for (uint32 i = 0; i < 物理体->m_粒子偏移和数量.y; ++i) {
			p[i + 物理体->m_粒子偏移和数量.x] = 体素坐标[i];
			v[i + 物理体->m_粒子偏移和数量.x] = 体素速度[i];
			m[i + 物理体->m_粒子偏移和数量.x] = 1;

			vm[i + 物理体->m_粒子偏移和数量.x] = {0,0,0,0};
			//粒子属性[i + 物理体->m_坐标块区.x] = { 0,0,0,0 };
		}
	}


	if (pbf.m_粒子类型状态.m_Mem.m_数量) {
		auto* 类型状态 = f_bm_ptr<S_ParticleAttr>(pbf.m_粒子类型状态);

		//for (auto& e : pbf.m_流体) {
		//	S_物理体* body = (S_物理体*)e.second;
		//	for (uint32 i = body->m_坐标块区.x; i < pbf.m_粒子数量; ++i) {
		//		类型状态[i] = f_物体类型和状态(E_物理体类型::E_物理体_流入, DEF_ParticleState_disable, 0);
		//	}
		//}
		for (auto& e : pbf.m_流入) {
			S_物理体* body = (S_物理体*)e.second;

			//auto* ob = ((S_物体*)body->m_Data);
			//if (!ob) break;
			//S_粒子系统配置* parsys = f_ob_fromParticle(ob);

			uint32 num = body->m_粒子偏移和数量.x + body->m_粒子偏移和数量.y;
			for (uint32 i = body->m_粒子偏移和数量.x; i < num; ++i) {
				类型状态[i] = f_物体类型和状态(E_物理体类型::E_物理体_流入, DEF_ParticleState_disable, 0);
			}
		}
		for (auto& e : pbf.m_流体) {
			S_物理体* body = (S_物理体*)e.second;
			uint32 num = body->m_粒子偏移和数量.x + body->m_粒子偏移和数量.y;
			for (uint32 i = body->m_粒子偏移和数量.x; i < num; ++i) {
				类型状态[i] = f_物体类型和状态(E_物理体类型::E_物理体_流入, DEF_ParticleState_enable, 100000000);
			}
		}
	}



	f_重置飞溅粒子(pbf);
}

void f_pbf_解算(S_PhysicspPBF& pbf, float32 时间步进) {
	
	auto& sim = f_buf_PBF解算参数_at(pbf.m_解算参数);
	sim.m_dt = 时间步进;
	sim.numSubsteps = 3;

	f_ob_构建底层层光追加速结构(pbf.m_碰撞物体);
	f_ob_构建顶层光追加速结构(pbf.m_碰撞物体, pbf.m_计数层);
	f_ob_光追加速结构描述集(pbf.m_计数层->m_光追顶层加速结构, &(pbf.m_计数层->m_光追描述集));

	
	for (uint32 k = 0; k < 1; ++k) {
		pbf.f_划分粒子();
		
		pbf.f_排序粒子();
		
		pbf.m_NumSubsteps = 3;
		//float32 子步长 = 时间步进 / pbf.m_NumSubsteps;
		float32 子步长 = 时间步进;
		
		for (uint32 i = 0; i < pbf.m_NumSubsteps; ++i) {
			pbf.f_计算力(子步长);
		}
	}
	
	if (pbf.m_开启飞溅粒子) {
		pbf.f_生成飞溅粒子(时间步进);

		pbf.f_发射飞溅粒子();
	}
}

void f_pbf_取调试粒子(S_PhysicspPBF& pbf, S_物体* ob, uint8 调试信息类型) {
	if(pbf.m_坐标.m_Mem.m_数量 <= 0) return;

	static int32 particleID = -1;
	if(particleID >= int32(pbf.m_坐标.m_Mem.m_数量 - 1)) particleID = -1;

	switch (调试信息类型) {
		case 0: {
			//std::cout<<"pbf.m_有效粒子数量 " << pbf.m_有效粒子数量 << std::endl;
			auto* me = f_ob_getMesh(ob, 0);
			uint32 num = pbf.m_坐标.m_Mem.m_数量 + pbf.m_有效飞溅粒子数量;

			f_mesh_切换顶点类型(me, E_顶点组合标志::e_坐标_法线_UV, num);
			
			S_PBF_ParticleDEBUG_ConstPush 参数;
			参数.m_Address_Particle = f_buf_getOffsetAddress(pbf.m_坐标);
			参数.m_Address_Acceleration = f_buf_getOffsetAddress(pbf.m_速度和年龄);
			参数.m_Address_SplashIndexKey = 0;
			参数.m_Address_Vert = f_buf_getOffsetAddress(*me->m_顶点);
			参数.m_density = 0.05;
			f_GPU_run计算(pbf.m_GPU计算_粒子可视, { uint32(pbf.m_坐标.m_Mem.m_数量), 1, 1 }, &参数, sizeof(S_PBF_ParticleDEBUG_ConstPush));


			if (pbf.m_飞溅坐标.m_Mem.m_数量) {
				参数.m_Address_Particle = f_buf_getOffsetAddress(pbf.m_飞溅坐标);
				参数.m_Address_Acceleration = f_buf_getOffsetAddress(pbf.m_飞溅速度);
				参数.m_Address_SplashIndexKey = f_buf_getOffsetAddress(pbf.m_飞溅粒子发射排序键值A);
				参数.m_Address_Vert = f_buf_getOffsetAddress(*me->m_顶点, pbf.m_坐标.m_Mem.m_数量);
				参数.m_density = 60;
				f_GPU_run计算(pbf.m_GPU计算_粒子可视, { pbf.m_有效飞溅粒子数量, 1, 1 }, &参数, sizeof(S_PBF_ParticleDEBUG_ConstPush));
			}
			break;

		}
		case 1: {
			auto* me = f_ob_getMesh(ob, 1);
			uint32 num = pbf.m_单元粒子索引网格.m_Mem.m_数量;

			f_mesh_切换顶点类型(me, E_顶点组合标志::e_坐标_法线_UV, num);

			S_PBF_DomainDEBUG_ConstPush 参数;
			参数.m_Address_Grid = f_buf_getOffsetAddress(pbf.m_单元粒子索引网格);
			参数.m_Address_Vert = f_buf_getOffsetAddress(*me->m_顶点);
			参数.m_dim = _iVec3(pbf.m_网格分辨率);
			参数.m_gridOffset = pbf.m_域偏移;
			参数.m_cellSize = pbf.m_网格单元大小;
			f_GPU_run计算(pbf.m_GPU计算_域可视, pbf.m_网格分辨率, &参数, sizeof(S_PBF_DomainDEBUG_ConstPush));
			break;

			if (num) {
				auto* ValueKey = f_buf_uVec2_ptr(pbf.m_排序键值);
				uvec2* keyOffset = f_buf_uVec2_ptr(pbf.m_单元粒子索引网格);

				std::vector<S_VNT1> 包围盒;
				for (uint32 z = 0; z < pbf.m_网格分辨率.z; ++z) {
					for (uint32 y = 0; y < pbf.m_网格分辨率.y; ++y) {
						for (uint32 x = 0; x < pbf.m_网格分辨率.z; ++x) {
							uint32 offset = f_glsl_CoordToIndex({ x,y,z }, pbf.m_网格分辨率);
							//std::cout << "单元粒子索引网格 " << x << " " << y << " " << " " << z << " " << offset << " " << gridIndex[offset].x << std::endl;

							if (keyOffset[offset].y) {
								ivec3 c = f_glsl_IndexToCoord(ValueKey[keyOffset[offset].x].y, pbf.m_网格分辨率);

								S_VNT1 vert;
								vert.vert = _Vec3(c) * pbf.m_网格单元大小 + pbf.m_域偏移;
								vert.normal = _Vec3(pbf.m_网格单元大小);
								vert.UV = {};

								包围盒.push_back(vert);
							}
							
						}
					}
				}

				//ivec3 currentCoord = f_glsl_IndexToCoord(ValueKey[particleID].y, pbf.m_网格分辨率);
				//
				//for (int32 z = -1; z <= 1; ++z) {
				//	for (int32 y = -1; y <= 1; ++y) {
				//		for (int32 x = -1; x <= 1; ++x) {
				//			ivec3 coord = vec_Max(currentCoord + ivec3{x, y, z}, ivec3{});
				//			coord = vec_Min(_iVec3(pbf.m_网格分辨率) - 1, coord);
				//
				//			uint neighborCoordIndex = f_glsl_CoordToIndex(_uVec3(coord), pbf.m_网格分辨率);
				//
				//			uint32 BinarySearch_offset = pbf.m_排序键值.m_Mem.m_数量 >> 1;
				//			uint32 BinarySearch_step = BinarySearch_offset;
				//			bool 找到 = false;
				//			
				//			if (keyOffset[neighborCoordIndex].x != 0xffffffff) {
				//				找到 = true;
				//			}
				//			
				//			if (找到) {
				//				ivec3 c = f_glsl_IndexToCoord(neighborCoordIndex, pbf.m_网格分辨率);
				//
				//				S_VNT1 vert;
				//				vert.vert = _Vec3(c) * pbf.m_网格单元大小 + pbf.m_域偏移;
				//				vert.normal = _Vec3(pbf.m_网格单元大小);
				//				vert.UV = {};
				//
				//				包围盒.push_back(vert);
				//			}
				//		}
				//	}
				//}

				f_mesh_fill顶点数据(f_ob_getMesh(ob, 1), 包围盒);
			}
			me->m_Color = { 50,255,255,255 };
			break;
		}
		default:
			break;
	}
}

void f_pbf_初始化解算参数(S_PBF_Params& p) {
	
	p.m_Gravity = {0.0f, -9.8f, 0.0f};
	p.m_Wind = {0,0,0};


	p.radius = 0.2f;
	p.viscosity = 0.2f;
	p.dynamicFriction = 0.0f;
	p.staticFriction = 0.0f;
	p.particleFriction = 0.0f; 
	p.freeSurfaceDrag = 0.0f;
	p.drag = 0.0f;
	p.lift = 0.0f;
	

	p.fluidRestDistance = 0.0f;
	p.solidRestDistance = 0.0f;
	p.rest_density = 100;


	p.anisotropyScale = 1.0f;
	p.anisotropyMin = 0.1f;
	p.anisotropyMax = 2.0f;
	p.smoothing = 1.0f;



	p.dissipation = 0.0f;
	p.damping = 0.0f;
	p.particleCollisionMargin = p.radius * 0.05;
	p.shapeCollisionMargin = 0.0f;
	p.collisionDistance = 0.0f;
	p.sleepThreshold = 0.0f;
	p.shockPropagation = 0.0f;
	p.restitution = 0.0f;


	p.maxSpeed = FLT_MAX;
	p.maxAcceleration = 10.1f;



	p.relaxationFactor = 1.0f;
	p.solidPressure = 1.0f;
	p.adhesion = 0.0f;
	//p.cohesion = 0.1025f;
	p.cohesion = 0.51;
	p.surfaceTension = 0.001f;
	p.vorticityConfinement = 0.0f;
	p.buoyancy = 1.0f;


	p.diffuseThreshold = 0.03;
	p.diffuseBuoyancy = 1.0f;
	p.diffuseDrag = 0.8f;
	p.diffuseBallistic = 16;
	p.diffuseLifetime = 0.5f;



}

void f_pbf_分配飞溅粒子(S_PhysicspPBF& pbf, bool 是否开启, uint32 分配数量) {
	pbf.m_开启飞溅粒子 = 是否开启;
}

void f_pbf_添加力(S_PhysicspPBF& pbf, const std::vector<S_PBF_force>& 力) {
	uint32 num = 力.size();
	f_bm_fill(pbf.m_力, 力.data(), num);
}

void f_pbf_set模拟参数(S_PhysicspPBF& pbf, const S_PBF_Params& 模拟参数) {
	*f_buf_PBF解算参数_ptr(pbf.m_解算参数) = 模拟参数;
}

void f_pbf_发射粒子(S_PhysicspPBF& pbf, S_物理体* body, const S_Vec3Array* point, const S_Vec3Array* vel) {
	uint32 num = max(point->count, vel->count);

	bool 位置多例 = point->count >= num;
	bool 速度多例 = vel->count >= num;
	//return;

	auto* ob = ((S_物体*)body->m_Data);
	S_粒子系统配置* parsys = f_ob_fromParticle(ob);
	

	vec3* particle = f_buf_Vec3_ptr(pbf.m_坐标);
	vec4* velocity = f_buf_Vec4_ptr(pbf.m_速度和年龄);
	auto* 类型状态 = f_bm_ptr<S_ParticleAttr>(pbf.m_粒子类型状态);

	uint32 index = 0;
	uint32 流体粒子数量 = body->m_粒子偏移和数量.x + body->m_粒子偏移和数量.y;

	srand(uint32(particle));
	for (uint32 i = body->m_粒子偏移和数量.x; i < 流体粒子数量; ++i) {
		
		if (velocity[i].w >= 类型状态[i].m_life) {
			float32 寿命 = parsys->m_初始寿命 * min(parsys->m_寿命随机比 + f_random_getF32(), 1);

			particle[i] = point->ptr_userData[位置多例 ? index : 0];
			velocity[i] = _Vec4(vel->ptr_userData[速度多例 ? index : 0], 0);
			类型状态[i] = f_物体类型和状态(E_物理体类型::E_物理体_流入, DEF_ParticleState_enable, 寿命);

			++index;

			if (index >= num) {
				break;
			}
		}
	}
}

void f_pbf_更新粒子渲染(S_PhysicspPBF& pbf, float32 子帧步进) {
	auto simP = f_buf_PBF解算参数_ptr(pbf.m_解算参数)[0];
	//return;
	for (auto& e : pbf.m_流入) {
		S_物体* 物体 = f_phy_get粒子物体对象(e.second);

		S_粒子系统配置* psys = f_ob_fromParticle(物体);
		
		auto* me = f_ob_getMesh(物体, E_物体网格元素类型::e_MT_光照);
		auto r = f_phy_get物体体粒子区间(e.second);

		const auto* vert = f_bm_ptr<vec3>(pbf.m_坐标);
		const auto* 年龄 = f_bm_ptr<vec4>(pbf.m_速度和年龄);
		const auto* 类型状态 = f_bm_ptr<S_ParticleAttr>(pbf.m_粒子类型状态);

		std::vector<Mat44f> aabb;
		//std::vector<S_Aabb> aabb;
		std::vector<vec3> 坐标;
		std::vector<vec3> 速度;
		aabb.reserve(r.y);
		坐标.reserve(r.y);
		速度.reserve(r.y);

		if (子帧步进 >= 0 && pbf.m_前一帧坐标.m_Mem.m_数量 >= pbf.m_坐标.m_Mem.m_数量) {
			
			if (E_粒子更新属性::e_pu_位置 & psys->m_包含属性) {
				const auto* vert_prev = f_bm_ptr<vec3>(pbf.m_前一帧坐标);
				for (uint32 i = 0; i < r.y; ++i) {
					uint32 index = i + r.x;

					if (年龄[index].w < 类型状态[index].m_life) {
						auto p = vert[index] + (vert_prev[index] - vert[index]) * 子帧步进;
						坐标.push_back(p);
						aabb.push_back(f_mat44_构建XYZ变换矩阵({ p, {}, _Vec3(psys->m_初始粒子大小) }));
					}
				}

				f_set粒子位置(psys, 坐标.data(), 坐标.size());
			}

			if (E_粒子更新属性::e_pu_速度 & psys->m_包含属性) {
				const auto* vert_prev = f_bm_ptr<vec3>(pbf.m_前一帧坐标);
				for (uint32 i = 0; i < r.y; ++i) {
					uint32 index = i + r.x;

					if (年龄[index].w < 类型状态[index].m_life) {
						auto p = (vert_prev[index] - vert[index]);
						速度.push_back(p);
					}
				}

				f_set粒子速度(psys, 速度.data(), 速度.size());
			}
		}
		else {
			for (uint32 i = 0; i < r.y; ++i) {
				uint32 index = i + r.x;

				if (年龄[index].w < 类型状态[index].m_life) {
					//aabb.push_back({ vert[index] - simP.radius * 0.5 , vert[index] + simP.radius * 0.5 });
					aabb.push_back(f_mat44_构建XYZ变换矩阵({ vert[index], {}, _Vec3(psys->m_初始粒子大小) }));
				}
			}
		}
		//f_surface_fill顶点数据(me, aabb);
		f_ob_set实例数量(物体, aabb.size(), false);
		f_bm_fill(物体->m_变换矩阵, aabb.data(), aabb.size());
	}
}


#include <locale>
#include <codecvt>

bool f_pbf_读取缓存(S_PhysicspPBF& pbf, const std::string& path, E_物理缓存方式 缓存方式, bool 前一帧) {
	if(f_file_文件是否存在(path) == false) return false;

	auto f = fopen(path.c_str(), "rb");
	if (f) {
		switch (缓存方式) {
			case E_物理缓存方式::e_phyCache_重播: {
				if (前一帧) {
					f_文件块_读缓存数据块(f, pbf.m_前一帧坐标, false);
					//f_文件块_读序列数据块(f, pbf.m_速度和年龄, false);
				}
				else {
					f_文件块_读缓存数据块(f, pbf.m_坐标, false);
					f_文件块_读缓存数据块(f, pbf.m_速度和年龄, false);
				}
				
				break;
			}
			case E_物理缓存方式::e_phyCache_模块: {
				break;
			}
			case E_物理缓存方式::e_phyCache_粒子: {
				break;
			}
			default:
				break;
		}
		
		fclose(f);
		return true;
	}
	return false;
}

void f_pbf_写入缓存(S_PhysicspPBF& pbf, const std::string& path, E_物理缓存方式 缓存方式) {
	auto f = fopen(path.c_str(), "wb");
	if (f) {
		switch (缓存方式) {
			case E_物理缓存方式::e_phyCache_重播: {
				f_bm_copy(pbf.m_前一帧坐标, pbf.m_坐标);
				f_文件块_写缓存数据块(f, pbf.m_坐标, false);
				f_文件块_写缓存数据块(f, pbf.m_速度和年龄, false);
				break;
			}
			case E_物理缓存方式::e_phyCache_模块: {
				break;
			}
			case E_物理缓存方式::e_phyCache_粒子: {
				break;
			}
			default:
				break;
		}

		fclose(f);
	}
}


bool f_pbf_内部重构(S_PhysicspPBF& pbf) {

	if (pbf.m_坐标.m_Mem.m_数量 != pbf.m_加速度.m_Mem.m_数量) {
		f_pbf_重构(pbf);
		return true;
	}

	return false;
}






